// 定义一个 构造函数
// 需要两个参数 标签对象 和 数据信息
class setBanner {
    constructor(element, array) {
        // 存储 参数
        this.ele = element;
        this.arr = array;

        // 获取 ul ol 标签对象
        this.ul = this.ele.querySelector('ul');
        this.ol = this.ele.querySelector('ol');

        // 定义 实例化对象的属性和属性值
        this.ullis;
        this.ollis;
        this.length = this.arr.length;
        this.liWidth;
        this.index = 1;
        this.intVal;
        this.bool = true;
    }

    // 定义函数方法

    // 定义一个函数 这个函数专门调用执行 所有需要独立执行的函数程序
    // 这样的函数称为 入口函数 
    // 一般定义名称为 init
    init(){
        this.setPage();
        this.autoLoop();
        this.setMouse();
        this.setClick();
        this.hid();
    }


    // 1 动态渲染生成页面
    setPage() {
        // 定义 变量 存储 生成的字符串
        let ulStr = '';
        let olStr = '';

        // 根据 数组 动态生成字符串标签对象
        // 没有使用this, 使用匿名函数 或者 箭头函数 都可以
        this.arr.forEach(function (item, key) {
            // 生成 ul>li
            ulStr += `<li><img src="../image/${item.name}"></li>`;

            // 生成 ol>li
            olStr += key === 0 ? `<li class="active" name="focus" num="${key}"></li>` : `<li name="focus" num="${key}"></li>`;
        })

        // 将 生成内容 写入 标签
        this.ul.innerHTML = ulStr;
        this.ol.innerHTML = olStr;

        // 获取 所有的 ul>li  ol>li
        this.ullis = this.ele.querySelectorAll('ul>li');
        this.ollis = this.ele.querySelectorAll('ol>li');

        // 克隆 原始ul 中 第一个和最后一个li标签
        const first = this.ullis[0].cloneNode(true);
        const last = this.ullis[this.length - 1].cloneNode(true);

        // 克隆的第一个写入ul最后 克隆的最后有一个写入ul起始
        this.ul.appendChild(first);
        this.ul.insertBefore(last, this.ullis[0]);

        // 重新设定ul宽度
        // 是 当前 li个数 * li宽度
        this.liWidth = this.ullis[0].offsetWidth;

        this.ul.style.width = this.liWidth * (this.length + 2) + 'px';

        // ul 向左 定位 一个li 宽度
        this.ul.style.left = -this.liWidth + 'px';
    }

    // 2 自动轮播
    autoLoop() {
        // 定义定时器 每间隔时间 执行程序
        // 使用this 必须要 修改为箭头函数
        this.intVal = setInterval(() => {
            // 变量累加
            this.index++;

            // 调用函数 设定 焦点样式
            this.setFocusStyle();

            move(this.ul, { left: -this.liWidth * this.index }, this.moveEndFun.bind(this));

        }, 3000)
    }

    // 3 轮播动画终止回调函数
    //  当前函数执行的方式是 回调 函数 
    //  是在 move运动函数中 调用的
    //  move() 函数 是 声明式 函数 this指向是 window
    moveEndFun() {
        // 回调函数 一般 this 指向都会改变
        // 当前是 变为 undefined
        // 必须要 改变this为 实例化对象
        // console.log( this );

        // 判断 this.index 数值

        // 是最后一个 赋值 1 
        if (this.index === this.length + 2 - 1) {
            // 赋值 1 
            this.index = 1;
            // 重新定位 ul标签对象
            this.ul.style.left = -this.liWidth * this.index + 'px';

            // 是 0 赋值 倒数第二个索引下标
        } else if (this.index === 0) {
            // 赋值 倒数第二个
            this.index = this.length + 2 - 2;
            // 重新定位 ul标签对象
            this.ul.style.left = -this.liWidth * this.index + 'px';
        }

        // 给变量赋值 true
        this.bool = true;
    }

    // 4 焦点样式设定
    setFocusStyle() {
        // 清除所有ol>li样式
        this.ollis.forEach((item, key) => {
            item.classList.remove('active');

            if (key === this.index - 1) {
                item.classList.add('active');
            }
        })

        if (this.index === this.length + 2 - 1) {
            this.ollis[0].classList.add('active');
        } else if (this.index === 0) {
            this.ollis[this.length - 1].classList.add('active');
        }

    }

    // 5 鼠标的移入移出
    setMouse() {
        this.ele.addEventListener('mouseenter', () => {
            clearInterval(this.intVal);
        })

        this.ele.addEventListener('mouseleave', () => {
            this.autoLoop();
        })
    }

    // 6 点击效果
    setClick() {
        // 给父级添加点击事件
        this.ele.addEventListener('click', e => {
            // 判断点击的是 左切换
            if (e.target.getAttribute('name') === 'left') {
                // 防止点击过快
                if (this.bool) {
                    this.bool = false;
                } else {
                    return;
                }

                // this.index 累减 1
                this.index--;

                // 调用函数 设定 焦点样式
                this.setFocusStyle();

                // 使用 move运动函数 运动完成切换
                move(this.ul, { left: -this.liWidth * this.index }, this.moveEndFun.bind(this));

                //  判断点击的是 右切换
            } else if (e.target.getAttribute('name') === 'right') {
                // 防止点击过快
                if (this.bool) {
                    this.bool = false;
                } else {
                    return;
                }

                // this.index 累加 1
                this.index++;

                // 调用函数 设定 焦点样式
                this.setFocusStyle();

                // 使用 move运动函数 运动完成切换
                move(this.ul, { left: -this.liWidth * this.index }, this.moveEndFun.bind(this));

                // 点击的是焦点按钮
            } else if (e.target.getAttribute('name') === 'focus') {
                // 防止点击过快
                if (this.bool) {
                    this.bool = false;
                } else {
                    return;
                }

                // this.index 赋值点击标签存储num值 +1
                this.index = e.target.getAttribute('num') - 0 + 1;

                // 调用函数 设定 焦点样式
                this.setFocusStyle();

                // 使用 move运动函数 运动完成切换
                move(this.ul, { left: -this.liWidth * this.index }, this.moveEndFun.bind(this));

            }
        })
    }

    // 7 浏览器最小化 
    hid() {
        // 给 整个 文档 添加事件 
        // visibilitychange 浏览器显示状态改变事件
        // 浏览器 显示状态 改变 就会触发 
        document.addEventListener('visibilitychange',  () => {
            // document.visibilityState 浏览器显示状态描述
            // hidden 表示 隐藏 
            if (document.visibilityState === 'hidden') {
                // 如果 浏览器是 隐藏/最小化 状态
                // 停止自动轮播
                clearInterval( this.intVal);

                // document.visibilityState 浏览器显示状态描述
                // visible 表示 显示 
            } else if (document.visibilityState === 'visible') {
                // 如果 浏览器是 显示 状态
                // 再次调用 自动轮播
                this.autoLoop();
            }
        })

        window.addEventListener( 'scroll' , function(){

            if ( $(window).scrollTop() > 1000) {
                clearInterval( this.intVal);
            } else if ($(window).scrollTop()<1000) {
                this.autoLoop();
            }
        })

    }

}

